# 评估模型
import numpy as np
from sklearn.metrics import f1_score, mean_absolute_error, mean_squared_error, precision_score, recall_score
from sklearn.model_selection import train_test_split
import cupy as cp

from model import als_wr_gpu, build_matrix


def evaluate_model(predictions, true_ratings, threshold=2.5):
    """
    评估模型的RMSE、MAE、Precision、Recall和F1值，只考虑交集部分
    """
    print("Evaluating...")
    
      # 如果predictions和true_ratings是cupy数组，则转换为numpy数组
    if isinstance(predictions, cp.ndarray):
        predictions = predictions.get()
    if isinstance(true_ratings, cp.ndarray):
        true_ratings = true_ratings.get()
    print("predictions::::::::::")
    # print(predictions)
    print(true_ratings)
    # 获取交集的用户和物品
    common_users = np.intersect1d(predictions.nonzero()[0], true_ratings.nonzero()[0])
    common_items = np.intersect1d(predictions.nonzero()[1], true_ratings.nonzero()[1])

    # 筛选交集部分的数据
    filtered_predictions = predictions[common_users, common_items]
    filtered_true_ratings = true_ratings[common_users, common_items]
    print(filtered_predictions)
    print(filtered_true_ratings)

    # 计算RMSE和MAE
    rmse = np.sqrt(mean_squared_error(filtered_true_ratings, filtered_predictions))
    mae = mean_absolute_error(filtered_true_ratings, filtered_predictions)

    # 将评分大于threshold的视为相关物品
    predicted_labels = filtered_predictions >= threshold
    true_labels = filtered_true_ratings >= threshold

    # 计算精度、召回率和F1值
    precision = precision_score(true_labels, predicted_labels, average='binary')
    recall = recall_score(true_labels, predicted_labels, average='binary')
    f1 = f1_score(true_labels, predicted_labels, average='binary')

    return rmse, mae, precision, recall, f1

# 比较不同算法的表现
def compare_algorithms(data):
    # 加载数据并构建评分矩阵
    ratings_matrix = build_matrix(data)
    
    # 分割数据为训练集和测试集
    train_data, test_data = train_test_split(data, test_size=0.2, random_state=42)
    train_matrix = build_matrix(train_data)
    test_matrix = build_matrix(test_data)
    
    # ALS-WR
    user_features, item_features = als_wr_gpu(train_matrix, num_features=20, lambda_reg=0.1, num_iterations=20)
    als_predictions = np.dot(user_features, item_features.T)
    rmse_als, mae_als, precision_als, recall_als, f1_als = evaluate_model(als_predictions, test_matrix.toarray())

    # 打印结果
    print(f"ALS-WR RMSE: {rmse_als}, MAE: {mae_als}, Precision: {precision_als}, Recall: {recall_als}, F1: {f1_als}")

    # 将结果映射到字典中
    results = {
            'RMSE': rmse_als,
            'MAE': mae_als,
            'Precision': precision_als,
            'Recall': recall_als,
            'F1': f1_als
    }
    return results